﻿/// <reference path="../jquery-vsdoc.js" />

//#region 为原生的DOM元素添加统一的辅助方法用于获取或设置值
HTMLElement.prototype.vl = function (_newValue) {
    if (!ObjHelper.IsEmpty(_newValue)) {
        $(this).vl(_newValue);
        return this;
    }
    else {
        return $(this).vl();
    }
};

HTMLElement.prototype.ID = function (_newId) {
    if (ObjHelper.IsEmpty(_newId)) {
        return $(this).ID();
    }
    else {
        $(this).ID(_newId);
        return this;
    }
};

HTMLElement.prototype.attr = function (_key, _value) {
    if (ObjHelper.IsEmpty(_value)) {
        return $(this).attr(_key);
    }
    else {
        $(this).attr(_key, _value);
        return this;
    }
}

HTMLElement.prototype.addClass = function (_style) {
    $(this).addClass(_style);
    return this;
};

HTMLElement.prototype.removeClass = function (_style) {
    $(this).removeClass(_style);
    return this;
};

HTMLElement.prototype.reset = function () {
    this.VL("");
    return this;
}
//#endregion

//#region 为jquery对象扩展一些方法，以保持与LiberUI控件对象的操作一致性
; (function ($) {
    //针对JQuery选择DOM元素后的扩展操作功能
    $.fn.extend({
        "ID": function (_newID) {
            /// <summary>
            /// 为JQuery对象提供与LiberUI控件一致的获取ID属性的方法
            /// </summary>
            /// <param name="_newID"></param>
            if (ObjHelper.IsEmpty(_newID)) {
                var cid = $(this).attr('id');
                if (!cid) {
                    cid = 'id' + Math.random();
                    $(this).attr('id', cid);
                }
                return cid;
            }
            else {
                $(this).attr('id', _newID);
                return $(this);
            }
        },

        "dispose": function () {
            /// <summary>
            /// 为JQuery对象提供与LiberUI控件一致的销毁自身的方法
            /// </summary>
            $.each(this, function () {
                $(this).remove('', false);
                delete this;
            });
        },

        "dom":function(_elm){
            if(ObjHelper.IsElement(_elm)){
                $(this).appendTo(_elm);
                return this;
            }
            else{
                return $(this);
            }
        },

        "reset":function(){
            return $(this).VL("");
        },

        "mask": function (_cnt) {
            /// <summary>
            /// 创建一个简单的遮罩层覆盖在指定元素之上
            /// </summary>
            var elm = $(this);

            //判断遮罩层是否已存在
            m = elm.children(".MaskLayer").eq(0);
            if (m.length==0) {
                m = $("<div class='MaskLayer'></div>");
                m.on("click", function (ev) { ev.stopPropagation(); ev.preventDefault(); });
                m.on("mousewheel", function (ev) { ev.stopPropagation(); ev.preventDefault(); })
                m.prependTo(elm);
            }
            m.children().remove();
            LayoutHelper.Layout2Parent(m.show(), "Cover", null);
            if (ObjHelper.IsElement(_cnt)) {
                m.append(_cnt);
                LayoutHelper.Layout2Parent(_cnt, "AllCenter", null);
            }
            return m;
        },

        "unmask": function () {
        	/// <summary>
        	/// 移除通过Mask方法创建的遮罩层
        	/// </summary>
        	/// <returns type=""></returns>
            $(this).children(".MaskLayer").remove();
            return this;
        },

        "coverTo": function (_target) {
            /// <summary>
            /// 将当前所选中的元素覆盖在目标元素上
            /// </summary>
            /// <param name="_target" type="JQuery DOM or DOM">要覆盖的目标元素</param>
            var cnt = $(this).css("position", "absolute")
                             .css("zIndex", 500).css("left", 0)
                             .css("bottom", 0)
                             .width($(_target).outerWidth())
                             .show();
            $(_target).append(cnt);
            return this;
        },

        "coverOff":function(){
            $(this).appendTo("body").hide();
            return this;
        },

        "editble": function () {
            var elm = $(this);
            if (elm.is("input") || elm.is("textarea")) {
                return true;
            }
            else {
                var atr = elm.attr("contenteditable");
                if (atr !== undefined) {
                    return atr;
                }
                else {
                    if (elm.data("Controller")!==undefined) {
                        return elm.data("Controller").editble;
                    }
                    else {
                        return false;
                    }
                }
            }
        },

        "disable":function(){
            var elm = $(this);
            if (elm.is("input") || elm.is("textarea")) {
                elm.attr("disabled", "disabled");
                return elm;
            }
            else {
                var atr = elm.attr("contenteditable");
                if (atr !== undefined) {
                    elm.attr("contentEditble", "false");
                    return atr;
                }
                else {
                    if (elm.data("Controller") !== undefined) {
                        return elm.data("Controller").disable();
                    }
                    else {
                        return false;
                    }
                }
            }
        },

        "enable":function(){
            var elm = $(this);
            if (elm.is("input") || elm.is("textarea")) {
                elm.removeAttr("disabled");
                return elm;
            }
            else {
                var atr = elm.attr("contentEditble");
                if (atr !== undefined) {
                    elm.attr("contentEditble", "true");
                    return atr;
                }
                else {
                    if (elm.data("Controller") !== undefined) {
                        return elm.data("Controller").enable();
                    }
                    else {
                        return false;
                    }
                }
            }
        },

        "vl": function (_newValue) {
            var elm = $(this);
            if (_newValue == undefined) {
                if (elm.is("input") || elm.is("textarea")) {
                    return elm.val();
                }
                else {
                    return elm.html();
                }
            }
            else {
                if (elm.is("input") || elm.is("textarea")) {
                    elm.val(_newValue);
                }
                else if (this.nodeType === 3 || this.nodeType === 8 || this.nodeType === 2) {
                    elm.text(_newValue);
                }
                else {
                    elm.html(_newValue);
                }
                return elm;
            }
        }
    })
})(jQuery);
//#endregion

mesh = function (newobj, old, refField) {
    /// <summary>
    /// 将old对象中已有的属性覆盖到新对象，没有的则保留新对象中的内容
    /// </summary>
    if (!refField) {
        if (Array.isArray(newobj) && Array.isArray(old)) {
            for (var i = 0; i < newobj.length; i++) {
                mesh(newobj[i], old[i]);
            }
        }
        else {
            for (var p in newobj) {
                if (Array.isArray(newobj[p]) && old && old.hasOwnProperty(p)) {
                    mesh(newobj[p], old[p]);
                }
                else if (old && old.hasOwnProperty(p)) {
                    newobj[p] = old[p];
                }
                else {
                }
            }
        }
    }
    else {
        //指定了参考字段
        if (Array.isArray(newobj) && Array.isArray(old)) {
            //对于数组，采取查找替换方式合并
            for (var i = 0; i < newobj.length; i++) {
                mesh(newobj[i], old.findObj(refField, newobj[i][refField]),refField);
            }
        }
        else {
            for (var p in newobj) {
                if (Array.isArray(newobj[p]) && old && old.hasOwnProperty(p)) {
                    mesh(newobj[p], old[p],refField);
                }
                else if (old && old.hasOwnProperty(p)) {
                    newobj[p] = old[p];
                }
                else {
                }
            }
        }
    }
    return newobj;
}

//#region 通用辅助工具
var ObjHelper = {
    IsEmpty: function (_obj) {
        /// <summary>
        /// 判定一个对象是否为空
        /// </summary>
        /// <param name="_obj">字符串、DOM、数组、JQuery对象</param>
        if (_obj == undefined || _obj == null) {
            return true;
        }
        else if (typeof _obj == "string") {
            return $.trim(_obj).length == 0;
        }
        else if (Array.isArray(_obj)) {
            return _obj.length == 0;
        }
        else if (_obj instanceof jQuery) {
            return _obj.length == 0;
        }
        else {
            return false;
        }
    },

    IsElement: function (_obj) {
        /// <summary>
        /// 判断目标对象是否为一个DOM元素或包含DOM元素的JQuery对象
        /// </summary>
        /// <param name="_obj"></param>
        /// <returns type=""></returns>
        if (ObjHelper.IsEmpty(_obj)) {
            return false;
        }
        else if (_obj.nodeType) {
            return _obj.nodeType === 1 || _obj.nodeType === 11;
        }
        else if (_obj instanceof jQuery) {
            return _obj.length > 0 && _obj[0].nodeType && _obj[0].nodeType === 1;
        }
        else {
            return false;
        }
    },

    IsFunc: function (_fn) {
        /// <summary>
        /// 判断目标是否为一个函数方法
        /// </summary>
        /// <param name="_fn">目标函数</param>
        /// <returns type=""></returns>
        if (ObjHelper.IsEmpty(_fn)) {
            return false;
        }
        else {
            return typeof _fn === "function";
        }
    },

    DisposeObj: function (_obj) {
        if (!_obj || ObjHelper.IsFunc(_obj)) {
            return;
        }
        else if (Array.isArray(_obj)) {
            var l = _obj.length;
            for (var i = 0; i < l; i++) {
                ObjHelper.DisposeObj(_obj[i]);
                _obj[i] = null;
            }
        }
        else if (typeof _obj === 'object') {
            if (_obj instanceof LController) {
                _obj.dispose();
            }
            else if (ObjHelper.IsElement(_obj)) {
                $(_obj).remove("", false);
            }
            else {
                for (var i in _obj) {
                    if (_obj.hasOwnProperty(i) && _obj !== _obj[i]) {
                        ObjHelper.DisposeObj(_obj[i]);
                        _obj[i] = undefined;
                    }
                }
            }
        }
    }
}
//#endregion

//#region 布局帮助类方法
var LayoutHelper = {
	Layout2Parent: function (_targetDOM, _mode, _offset, _absolute) {
		/// <summary>
		/// 将目标元素按指定方式定位到相对其父元素的位置
		/// </summary>
		/// <param name="_targetDOM"></param>
		/// <param name="_mode">定位模式[YCenter,XCenter,AllCenter,Cover]</param>
		/// <param name="_offset">偏移[top,bottom,left,right]</param>
		/// <param name="_absolute">是否使用绝对定位(正常情况下没有区别)</param>
	    var tgt = $(_targetDOM);
	    var isAbsolute=false;
		if (_absolute === true) {
		    isAbsolute = true;
		    tgt.css("position", "absolute");
		}

		var p = $(tgt.parent()[0]);
		var off = $.extend({ top: 0, bottom: 0, left: 0, right: 0 }, _offset);
		var h = tgt.outerHeight(true);
		if (h == 0) {
		    h = tgt[0].scrollHeight;
		}
		var w = tgt.outerWidth(true);
		var ph = p.height();
		var pw = p.width();

		switch (_mode) {
			case "YCenter":
				tgt.css("top", ((ph - h)/2 + off.top - off.bottom)+"px");
				break;
			case "XCenter":
				tgt.css("left", ((pw - w)/2 + off.left - off.right)+"px");
				break;
		    case "AllCenter":
				tgt.css("top", ((ph - h) / 2 + off.top - off.bottom)+'px');
				tgt.css("left", ((pw - w) / 2 + off.left - off.right)+'px');
				break;
		    case "Cover":
		        if (tgt.css("position") !== "fixed") {
		            tgt.css('position', 'absolute').css("top", 0).css("left", 0);
		        }   
		        tgt.css('height', ph + 'px').css('width', pw + 'px');
		        break;
		    case "Bottom":
		        tgt.css("top", 0 - ph).css("left", w - pw);
		        break;
		    default:
		        tgt.offset(off);
		        break;
		}
		p = null;
		off = null;
	},

	Layout2Wnd:function(_targetDOM,_mode,_offset){
	    /// <summary>
	    /// 将目标元素按指定方式定位到当前窗口的相对位置
	    /// </summary>
	    /// <param name="_targetDOM"></param>
	    /// <param name="_mode">定位模式[YCenter,XCenter,AllCenter,Cover]</param>
	    /// <param name="_offset">偏移[top,bottom,left,right]</param>
	    /// <param name="_absolute">是否使用绝对定位(正常情况下没有区别)</param>
	    var tgt = $(_targetDOM);
	    //tgt.css("position", "absolute");
	    tgt.css("position", "fixed");

	    var p = $("html");
	    //p = $("body");
	    var off = $.extend({ top: 0, bottom: 0, left: 0, right: 0 }, _offset);
	    var h = tgt.outerHeight(true);
	    if (h == 0) {
	        h = tgt[0].scrollHeight;
	    }
	    var w = tgt.outerWidth(true);
	    //var ph = p.height() + p[0].scrollTop;
	    //var pw = p.width() + p[0].scrollLeft;

	    th = document.body.clientHeight;
	    tw = document.body.clientWidth;

	    switch (_mode) {
	        case "YCenter":
	            tgt.css("top", ((th - h) / 2 + p[0].scrollTop + off.top - off.bottom) + 'px');
	            break;
	        case "XCenter":
	            tgt.css("left", ((tw - w + p[0].scrollLeft) / 2 + off.left - off.right) + 'px');
	            break;
	        case "AllCenter":
	            tgt.css("top", ((th-h) / 2 + p[0].scrollTop + off.top - off.bottom) + 'px');
	            tgt.css("left", ((tw - w + p[0].scrollLeft) / 2 + off.left - off.right) + 'px');
	            break;
	        case "Cover":
	            //tgt.css('position', 'absolute').css("top", 0).css("left", 0);
	            tgt.css('height', th + 'px').css('width', tw + 'px');
	            break;
	        case "Bottom":
	            tgt.css("top", 0 - th).css("left", w - tw);
	            break;
	        default:
	            tgt.offset(off);
	            break;
	    }
	    p = null;
	    off = null;
	},

	PosToBody: function (_refElm, _elm, _pos, _offset) {
		/// <summary>
		/// 将Body中的某个子元素定位到指定元素附近(注意：窗口尺寸改变时需重新定位)
		/// </summary>
		/// <param name="_refElm">定位的参照目标元素</param>
		/// <param name="_elm">要改变位置的元素（必须是body的直接子元素,且是绝对定位）</param>
		/// <param name="方位">方向定义（right-up,right,right-down,down,down-left(下左对齐),down-right(下右对齐),left-down,left,left-up,up,mid）</param>
		/// <param name="_offset">定位坐标偏移(可以是绝对数值，或相对参照目标的百分比)</param>

	    var refpos = _refElm.offset();  //获取参照目标相对body的偏移坐标
		var eh = _elm.innerHeight();
		var ew = _elm.innerWidth();
		var rw = _refElm.innerWidth();
		var rh = _refElm.innerHeight();
		if (!_offset) {
			_offset = { top: 0, left: 0 };
		}
		else {
			if (!_offset['top']) {
				_offset.top = 0;
			}
			else if (_offset.top.toString().slice(-1) === '%') {
				_offset.top = rh * parseFloat(_offset.top) / 100;
			}

			if (!_offset['left']) {
				_offset.left = 0;
			}
			else if (_offset.left.toString().slice(-1) === '%') {
				_offset.left = rw * parseFloat(_offset.left) / 100;
			}

		}
		var dst = {};

		switch (_pos) {
		    case "right-up":
		        dst.top = refpos.top - eh - _offset.top;
		        dst.left = refpos.left + rw + _offset.left;
		        //_elm.offset(dst);
		        break;
		    case "down-left":
		        dst.top = refpos.top + rh + _offset.top;
		        dst.left=refpos.left;
		        //_elm.offset(dst);
		        break;
		    case "cover":
		        dst.top = refpos.top;
		        dst.left = refpos.left;
		    case "down":
		        dst.top = refpos.top + rh + _offset.top;
		        dst.left = refpos.left-ew/2;
		        break;
		    case "down-right":
		        dst.top = refpos.top + rh + _offset.top;
		        dst.left = refpos.left-ew+rw;
		        break;
		    case "left-up":
		        dst.top = refpos.top-eh+_offset.top;
		        dst.left = refpos.left - ew + rw;
		        break;
			default:
				break;
		}
		_elm[0].style.z = _refElm[0].style.z + 1;
		_elm[0].style.position = 'absolute';
		switch (_elm.css('position')) {
		    case "absolute":
		        _elm.css('top', dst.top + 'px').css('left', dst.left + 'px');
		        break;
		    default:
		        _elm.css('top', dst.top + 'px').css('left', dst.left + 'px');
		        break;
		}
		
	}
};
//#endregion

//#region 键盘帮助类
function KeypressMonitor() {
	var instance = this;
	instance.Global = {};
	tgts = {};
	function onPress(ev) {
		var char = '';
		switch (ev.keyCode) {
			case 8:
				char = 'backspace';
				break;
			case 9:
				char = 'tab';
				break;
			case 13:
				char = 'enter';
				break;
			case 16:
				char = 'shift';
				break;
			case 17:
				char = 'ctrl';
				break;
			case 18:
				char = 'alt';
				break;
			case 20:
				char = 'capslock';
				break;
			case 32:
				char = 'space';
				break;
			case 186:
				if (ev.shiftKey) {
					char = ':'
				}
				else {
					char = ';';
				}
				break;
			case 188:
				if (ev.shiftKey) {
					char = '<';
				}
				else {
					char = ',';
				}
				break;
			case 190:
				if (ev.shiftKey) {
					char = '>'
				}
				else {
					char = '.';
				}
				break;
			default:
				char = String.fromCharCode(ev.keyCode);
				break;
		}
		ev = jQuery.Event(ev);
		var $elm = $(ev.originalEvent.srcElement);
		ev.Dom = $elm;
		var id = $elm.attr('id');

		if (instance.Global[char] && instance.Global[char].length > 0) {
		    //先看看有没有全局指定按键值的事件绑定
		    instance.Global[char][0].call(this, ev, char);
		}
		else if (instance.Global['*'] && instance.Global['*'].length > 0) {
            //再看看有没有全局所有按键的事件绑定
		    instance.Global['*'][0].call(this, ev, char);
		}
		else {

		}

	    //再看看有没有绑定特定元素
		if (tgts[id]) {
		    if (char != ''&&!tgts[id].handed) {
		        tgts[id].handed = true;
		        notifyKeyEvent(char, id, ev);
		    }
		    else {
		        tgts[id].handed = false;
		    }
		}
	};

	function onDown(ev) {
	    var char = '';
	    switch (ev.keyCode) {
	        case 8:
	            char = 'backspace';
	            break;
	        case 9:
	            char = 'tab';
	            break;
	        case 13:
	            if (ev.ctrlKey) {
	                char = 'ctrl+enter';
	            }
	            else {
	                char = 'enter';
	            }
	            break;
	        case 40:
	            char = 'down';
	            break;
	        case 38:
	            char = 'up';
	            break;
	        case 27:
	            char = 'esc';
	            break;
	    }
	    if (ObjHelper.IsEmpty(char)) {
	        return;
	    }
	    ev = jQuery.Event(ev);
	    var $elm = $(ev.originalEvent.srcElement);
	    ev.Dom = $elm;
	    var id = $elm.attr('id');
	    //先看看有没有全局事件绑定
	    if (instance.Global[char] && instance.Global[char].length > 0) {
	        instance.Global[char][0].call(this, ev, char);
	    }
	    else if (instance.Global['*'] && instance.Global['*'].length > 0) {
	        instance.Global['*'][0].call(this, ev, char);
	    }
	    else {

	    }

	    //再看看有没有绑定特定元素
	    if (tgts[id]) {
	        if (char != '' && !tgts[id].handed) {
	            tgts[id].handed = true;
	            notifyKeyEvent(char, id, ev);
	        }
	        else {
	            tgts[id].handed = false;
	        }
	    }
	};

	function onInput(ev) {
	    ev = jQuery.Event(ev);
	    var $elm = $(ev.originalEvent.srcElement);
	    ev.Dom = $elm;
	    var id = $elm.attr('id');
	    var char = '';
	    var v = $elm.vl();
	    char = v.slice(v.length - 1, v.length);
	    switch (char) {
	        case "。":
	            char = '.';
	            break;
	        case "，":
	            char = ',';
	            break;
	        case "：":
	            char = ":";
	            break;
	    }
	    //先看看有没有全局事件绑定
	    if (instance.Global[char] && instance.Global[char].length > 0) {
	        instance.Global[char][0].call(this, ev, char);
	    }
	    else if (instance.Global['*'] && instance.Global['*'].length > 0) {
	        instance.Global['*'][0].call(this, ev, char);
	    }
	    else {

	    }
	    //再看看有没有绑定特定元素
	    if (tgts[id]) {
	        if (char != '' && !tgts[id].handed) {
	            tgts[id].handed = true;
	            notifyKeyEvent(char, id, ev);
	        }
	        else {
	            tgts[id].handed = false;
	        }
	    }
	};

	function notifyKeyEvent(char, id, ev) {
	    ev.Char = char;
	    //首先看是否针对特定字符绑定了处理函数
	    var hs = tgts[id][char];
	    if (hs) {
	        for (var i = 0; i < hs.length; i++) {
	            if (ObjHelper.IsFunc(hs[i])) {
	                hs[i](ev, char);
	                if (ev.isPropagationStopped()) {
	                    break;
	                }
	            }
	        }

	    }
	    else {
	        //如果没有，看是否针对任意按键都绑定了处理事件
	        hs = tgts[id]['*'];
	        if (hs) {
	            for (var i = 0; i < hs.length; i++) {
	                if (ObjHelper.IsFunc(hs[i])) {
	                    hs[i](ev, char);
	                    if (ev.isPropagationStopped()) {
	                        break;
	                    }
	                }
	            }

	        }

	    }
	};

	window.onkeypress = onPress;
	window.onkeydown=onDown;
	window.oninput = onInput;

	this.on = function (_elm, _char, _fn) {
		/// <summary>
		/// 将指定方法绑定到目标Dom元素的特殊键盘事件
		/// </summary>
		/// <param name="_elm">要监视其键盘事件的元素</param>
		/// <param name="_char">要监视的特定输入值【enter,esc,space,dot,slash,backslash,backspace,colon】</param>
	    /// <param name="_fn">要回调的方法</param>
		var id = _elm.ID();
		var char = _char.toString().trim();
		if (!id) {
			id = 'id' + Math.random();
			_elm.ID(id);
		}

		if (!tgts[id]) {
		    tgts[id] = {};
		    tgts[id][char] = [];
		}
		else if (!tgts[id][char]) {
		    tgts[id][char] = [];
		}
		tgts[id][char].push(_fn);
		return instance;
	};

	this.off = function (_elm, _char, _fn) {
		/// <summary>
		/// 解除特定的或所有的事件绑定
		/// </summary>
		/// <param name="_elm"></param>
		/// <param name="_char"></param>
		/// <param name="_fn">指定要解除的方法，如果为空，则解除所有的事件绑定</param>
		var id = _elm.ID();
		if (ObjHelper.IsEmpty(_char)) {
			if (tgts.hasOwnProperty(id)) {
				ObjHelper.DisposeObj(tgts[id]);
				tgts[id] = null;
			}
		}
		else {
			//TODO：解除对特定键盘输入值的监控
		}
		return instance;
	};

	this.globalOn = function (_char, _fn) {
	    /// <summary>
	    /// 绑定全局特定按键（只有最后注册的方法会得到键盘消息，除非此方法被globalOff调用移除）
	    /// </summary>
	    /// <param name="_char"></param>
	    /// <param name="_fn"></param>
	    /// <returns type=""></returns>
	    if (!ObjHelper.IsFunc(_fn)) {
	        return this;
	    }
	    if (instance.Global.hasOwnProperty(_char)) {
	        var chs = instance.Global[_char];
	        //for (var i = 0; i < chs.length; i++) {
	        //    if (chs[i] === _fn) {
	        //        chs.swap(0, i);
	        //        return this;
	        //    }
	        //}
	        chs.push(_fn);
	        return this;
	    }
	    else {
	        instance.Global[_char] = [];
	        instance.Global[_char].push(_fn);
	        return this;
	    }
	};

	this.globalOff = function (_char, _fn) {
		/// <summary>
		/// 解除绑定的全局按键事件
		/// </summary>
		/// <param name="_char"></param>
		/// <param name="_fn"></param>
	    /// <returns type=""></returns>
	    if (!ObjHelper.IsFunc(_fn)) {
	        return this;
	    }
	    if (instance.Global.hasOwnProperty(_char)) {
	        var hs = instance.Global[_char];
	        for (var i = 0;i < hs.length; i++) {
	            if (hs[i] == _fn) {
	                hs.splice(i, 1);
	            }
	        }
	        return this;
	    }
	    return this;
	};

	this.Dispose = function () {
	    $(window).off('keypress', onPress).off('keydown', onDown);
	    window.oninput = null;
		ObjHelper.DisposeObj(instance);
		instance = null;
	};

	return instance;
}
if(!window.KeybordHelper) {
    KeybordHelper = new KeypressMonitor();
}

//#endregion

//#region Array对象操作方法扩展
Array.prototype.swap = function (_aIndex, _bIndex) {
    /// <summary>
    /// 交换数组中两个元素的位置,将_aIndex位置的元素替换为_bIndex位置的元素
    /// </summary>
    /// <param name="_aIndex" type="Number"></param>
    /// <param name="_bIndex" type="Number"></param>
    var tmp = this.splice(_bIndex, 1)[0];
    this.splice(_aIndex, 0, tmp);
    return this;
};
Array.prototype.eq = function (_index) {
    return this[_index];
};
Array.prototype.findObj = function (_field, _value, _newobj) {
    /// <summary>
    /// 在数组中查找具有指定属性或指定属性的值符合条件的第一个对象
    /// </summary>
    /// <param name="_field" type="type">属性名</param>
    /// <param name="_value" type="type">筛选值，不指定则返回第一个指定名称属性值不为null的</param>
    /// <param name="_newobj" type="type"></param>
    /// <returns type=""></returns>
    if (this.length == 0) {
        return null;
    }
    if (_value !== null && _value!== undefined) {
        for (var i = 0; i < this.length; i++) {
            if (this[i].hasOwnProperty(_field) && this[i][_field] == _value) {
                if (!ObjHelper.IsEmpty(_newobj)) {
                    this[i] = _newobj;
                }
                return this[i]
            }
        }
    }
    else {
        for (var i = 0; i < this.length; i++) {
            if (this[i].hasOwnProperty(_field)) {
                if (!ObjHelper.IsEmpty(_newobj)) {
                    this[i] = _newobj;
                }
                return this[i]
            }
        }
    }
    return null;
};
Array.prototype.findObjIndex = function (_field, _value, _newobj) {
    if (this.length == 0) {
        return -1;
    }
    for (var i = 0; i < this.length; i++) {
        if (this[i].hasOwnProperty(_field) && this[i][_field] == _value) {
            if (!ObjHelper.IsEmpty(_newobj)) {
                this[i] = _newobj;
            }
            return i;
        }
    }
    return -1;
};
Array.prototype.filter = function (_field, _value) {
    var rsult = [];
    if (this.length == 0) {
        return rsult;
    }
    if (!ObjHelper.IsEmpty(_value)) {
        for (var i = 0; i < this.length; i++) {
            if (this[i].hasOwnProperty(_field) && this[i][_field] == _value) {
                rsult.push(this[i])
            }
        }
    }
    else {
        for (var i = 0; i < this.length; i++) {
            if (this[i].hasOwnProperty(_field)) {
                rsult.push(this[i]);
            }
        }
    }
    return rsult;
};
Array.prototype.joinAttr = function (_field) {
    if (this.length == 0) {
        return [];
    }
    else {
        var rtn = [];
        for (var i = 0; i < this.length; i++) {
            if (this[i][_field]) {
                rtn.push(this[i][_field]);
            }
        }
        return rtn;
    }
};
Array.prototype.merge = function (_array, _pk, _fk) {
    var tmp = [];
    for (var i = 0; i < _array.length; i++) {
        var p = this.findObj(_pk, _array[i][_fk]);
        if (!p) {
            tmp.push(_array[i]);
        }
    }
    return this.push.apply(this, tmp);
};
Array.prototype.removeBy = function (_field, _value) {
    for (var i = 0; i < this.length; i++) {
        if (this[i][_field] && this[i][_field] === _value) {
            this.splice(i, 1);
        }
    }
    return this;
};
Array.prototype.removeOn = function (_value) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] && this[i]=== _value) {
            this.splice(i, 1);
        }
    }
    return this;
};
//#endregion

//#region String扩展方法
String.prototype.toJSON = function () {
    /// <summary>
    /// 将JSON格式的字符串转为标准的JSON对象
    /// </summary>
    /// <returns type=""></returns>
    if (this.length > 2) {
        return JSON.parse(this.replace(/&quot;/g, '\"').replace(/&gt;/g, '>').replace(/&lt;/g, '<'));
    }
    else {
        return null;
    }
};

String.prototype.noHtml = function () {
    /// <summary>
    /// 去除字符串中的Html标记
    /// </summary>
    /// <returns type=""></returns>
    return this.replace(/<\/?[^>]*>/g, '').replace(/[ | ]*\n/g, '\n').replace(/&nbsp;/ig, '').trim();
};

String.prototype.MD5 = function () {
    return $.md5(this);
};

//#endregion

//#region Object扩展方法

function GetXML(jsonObj,root) {
    var xml = "";
    if (jsonObj instanceof Array) {
        for (var i = 0; i < jsonObj.length; i++) {
            xml += GetXML(jsonObj[i],true);
        }
        return "<xml>" + xml + "</xml>";

    }
    else {
        for (var f in jsonObj) {
            if (jsonObj[f] && jsonObj.hasOwnProperty(f)) {
                xml += toXml(jsonObj[f], f, "");
            }
        }
    }
    if (!root) {
        xml = "<xml>" + xml.replace(/\t|\n/g, "") + "</xml>";
    }
    else {
        xml = xml.replace(/\t|\n/g, "");
    }

    return xml;
}

function toXml(v, name, ind) {
    var xml = "";
    if (v instanceof Array) {
        for (var i = 0, n = v.length; i < n; i++)
            xml += ind + toXml(v[i], name, ind + "\t") + "\n";
    }
    else if (typeof (v) == "object") {
        var hasChild = false;
        xml += ind + "<" + name;
        for (var m in v) {
            if (m.charAt(0) == "@")
                xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
            else
                hasChild = true;
        }
        xml += hasChild ? ">" : "/>";
        if (hasChild) {
            for (var m in v) {
                if (m == "#text")
                    xml += v[m];
                else if (m == "#cdata")
                    xml += "<![CDATA[" + v[m] + "]]>";
                else if (m.charAt(0) != "@")
                    xml += toXml(v[m], m, ind + "\t");
            }
            xml += (xml.charAt(xml.length - 1) == "\n" ? ind : "") + "</" + name + ">";
        }
    }
    else if (typeof (v) == "function") {
        return "";
    }
    else if(v!==undefined&&v!==null){
        xml += ind + "<" + name + ">" + v.toString()+ "</" + name + ">";
    }
    else {

    }
    return xml;
}

//#endregion

//#region Number对象的扩展方法
Number.prototype.roundTo = function (fix) {
    /// <summary>
    /// 高精度四舍五入到指定位数
    /// </summary>
    /// <param name="fix"></param>
    return Math.round(this * Math.pow(10, fix))/ Math.pow(10, fix);
}
Number.prototype.formatPercent = function (fix) {
    /// <summary>
    /// 带百分号，并固定小数部分的位数
    /// </summary>
    /// <param name="fix" type="type"></param>
    /// <returns type=""></returns>
    if (fix === undefined||fix===null) {
        fix = 0;
    }
    return (this * 100).toFixed(fix) + '%';
}
Number.prototype.toThousands = function () {
    /// <summary>
    /// 将数字按千分位分隔符
    /// </summary>
    /// <returns type=""></returns>
    var src=(this || 0).toString().split('.');
    var num = src[0];
    var result=""
    if (src.length > 1) {
        result = '.' + src[1];
    }

    while (num.length > 3) {
        result = ',' + num.slice(-3) + result;
        num = num.slice(0, num.length - 3);
    }
    if (num) { result = num + result; }
    return result;
}
Number.prototype.fixLength = function (len) {
    /// <summary>
    /// 将数字格式化为固定长度的字符串
    /// </summary>
    /// <param name="len" type="type"></param>
    /// <returns type=""></returns>
    var ln = this.toString().length;
    var num = this;
    while (ln < len) {
        num = "0" + num;
        ln += 1;
    }
    return num;
}

//#endregion

//#region 时间对象的扩展方法
//--------------------------------------------------- 
// 判断闰年 
//--------------------------------------------------- 
Date.prototype.isLeapYear = function() 
{ 
    return (0==this.getYear()%4&&((this.getYear()%100!=0)||(this.getYear()%400==0)));
} 
 
//--------------------------------------------------- 
// 日期格式化 
// 格式 YYYY/yyyy/YY/yy 表示年份 
// MM/M 月份 
// W/w 星期 
// dd/DD/d/D 日期 
// hh/HH/h/H 时间 
// mm/m 分钟 
// ss/s 秒 
// SS/S 毫秒
//--------------------------------------------------- 
Date.prototype.format = function(formatStr) 
{ 
    var str = formatStr;
    var Week = ['日', '一', '二', '三', '四', '五', '六'];

    str = str.replace(/yyyy|YYYY/, this.getFullYear());
    str = str.replace(/yy|YY/, (this.getYear() % 100) > 9 ? (this.getYear() % 100).toString() : '0' + (this.getYear() % 100));

    str = str.replace(/MM/g, this.getMonth() >= 9 ? (this.getMonth()+1).toString() : '0' + (this.getMonth()+1));
    str = str.replace(/M/g, this.getMonth()+1);

    str = str.replace(/w|W/g, Week[this.getDay()]);

    str = str.replace(/dd|DD/, this.getDate() > 9 ? this.getDate().toString() : '0' + this.getDate());
    str = str.replace(/d|D/g, this.getDate());

    str = str.replace(/hh|HH/, this.getHours() > 9 ? this.getHours().toString() : '0' + this.getHours());
    str = str.replace(/h|H/g, this.getHours());
    str = str.replace(/mm/g, this.getMinutes() > 9 ? this.getMinutes().toString() : '0' + this.getMinutes());
    str = str.replace(/m/g, this.getMinutes());

    str = str.replace(/ss|SS/, this.getSeconds() > 9 ? this.getSeconds().toString() : '0' + this.getSeconds());
    str = str.replace(/s|S/g, this.getSeconds());

    return str;
}
 
//+--------------------------------------------------- 
//| 求两个时间的天数差 日期格式为 YYYY-MM-dd 
//+--------------------------------------------------- 
function daysBetween(DateOne,DateTwo) 
{
    var date1 = DateOne.replace("/", "-");
    var date2 = DateTwo.replace("/", "-");
    var OneMonth = date1.substring(5, date1.lastIndexOf('-'));
    var OneDay = date1.substring(date1.length, date1.lastIndexOf('-') + 1);
    var OneYear = date1.substring(0, date1.indexOf('-'));
    var TwoMonth = date2.substring(5, date2.lastIndexOf('-'));
    var TwoDay = date2.substring(date2.length, date2.lastIndexOf('-') + 1);
    var TwoYear = date2.substring(0, date2.indexOf('-'));
 
    var cha=((Date.parse(OneMonth+'/'+OneDay+'/'+OneYear)- Date.parse(TwoMonth+'/'+TwoDay+'/'+TwoYear))/86400000);
    return cha; 
} 
 
//+--------------------------------------------------- 
//| 日期计算 
//+--------------------------------------------------- 
Date.prototype.dateAdd = function(strInterval, Number) { 
    var dtTmp = this; 
    switch (strInterval) { 
        case 's' :return new Date(Date.parse(dtTmp) + (1000 * Number)); 
        case 'n' :return new Date(Date.parse(dtTmp) + (60000 * Number)); 
        case 'h' :return new Date(Date.parse(dtTmp) + (3600000 * Number)); 
        case 'd' :return new Date(Date.parse(dtTmp) + (86400000 * Number)); 
        case 'w' :return new Date(Date.parse(dtTmp) + ((86400000 * 7) * Number)); 
        case 'q' :return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number*3, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
        case 'm' :return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
        case 'y' :return new Date((dtTmp.getFullYear() + Number), dtTmp.getMonth(), dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
    } 
} 
 
//+--------------------------------------------------- 
//| 比较日期差 dtEnd 格式为日期型或者 有效日期格式字符串 
//+--------------------------------------------------- 
Date.prototype.dateDiff = function(strInterval, dtEnd) { 
    var dtStart = this; 
    if (typeof dtEnd == 'string' )//如果是字符串转换为日期型 
    { 
        dtEnd = StringToDate(dtEnd); 
    } 
    switch (strInterval) { 
        case 's' :return parseInt((dtEnd - dtStart) / 1000); 
        case 'n' :return parseInt((dtEnd - dtStart) / 60000); 
        case 'h' :return parseInt((dtEnd - dtStart) / 3600000); 
        case 'd' :return parseInt((dtEnd - dtStart) / 86400000); 
        case 'w' :return parseInt((dtEnd - dtStart) / (86400000 * 7)); 
        case 'm' :return (dtEnd.getMonth()+1)+((dtEnd.getFullYear()-dtStart.getFullYear())*12) - (dtStart.getMonth()+1);
        case 'y' :return dtEnd.getFullYear() - dtStart.getFullYear(); 
    } 
} 
 
//+--------------------------------------------------- 
//| 日期输出字符串，重载了系统的toString方法 
//+--------------------------------------------------- 
Date.prototype.toString = function(showWeek) 
{
    var myDate = this;
    try{
        var str = myDate.format("yyyy-MM-dd");
        if (showWeek) 
        { 
            var Week = ['日','一','二','三','四','五','六']; 
            str += ' 星期' + Week[myDate.getDay()]; 
        } 
        return str; 
    }
    catch (ex) {
        return "";
    }
} 
 
//+--------------------------------------------------- 
//| 日期合法性验证 
//| 格式为：YYYY-MM-DD或YYYY/MM/DD 
//+--------------------------------------------------- 
function isValidDate(DateStr) 
{ 
    var sDate=DateStr.replace(/(^\s+|\s+$)/g,''); //去两边空格; 
    if(sDate=='') return true; 
    //如果格式满足YYYY-(/)MM-(/)DD或YYYY-(/)M-(/)DD或YYYY-(/)M-(/)D或YYYY-(/)MM-(/)D就替换为'' 
    //数据库中，合法日期可以是:YYYY-MM/DD(2003-3/21),数据库会自动转换为YYYY-MM-DD格式 
    var s = sDate.replace(/[\d]{ 4,4 }[\-/]{ 1 }[\d]{ 1,2 }[\-/]{ 1 }[\d]{ 1,2 }/g,'');
    if (s=='') //说明格式满足YYYY-MM-DD或YYYY-M-DD或YYYY-M-D或YYYY-MM-D 
    { 
        var t=new Date(sDate.replace(/\-/g,'/')); 
        var ar = sDate.split(/[-/:]/); 
        if(ar[0] != t.getYear() || ar[1] != t.getMonth()+1 || ar[2] != t.getDate()) 
        { 
            //alert('错误的日期格式！格式为：YYYY-MM-DD或YYYY/MM/DD。注意闰年。'); 
            return false; 
        } 
    } 
    else
    { 
        //alert('错误的日期格式！格式为：YYYY-MM-DD或YYYY/MM/DD。注意闰年。'); 
        return false; 
    } 
    return true; 
} 

//+--------------------------------------------------- 
//| 把日期分割成数组 
//+--------------------------------------------------- 
Date.prototype.toArray = function() 
{ 
    var myDate = this; 
    var myArray = Array(); 
    myArray[0] = myDate.getFullYear(); 
    myArray[1] = myDate.getMonth(); 
    myArray[2] = myDate.getDate(); 
    myArray[3] = myDate.getHours(); 
    myArray[4] = myDate.getMinutes(); 
    myArray[5] = myDate.getSeconds(); 
    return myArray; 
} 
 
//+--------------------------------------------------- 
//| 取得日期数据信息 
//| 参数 interval 表示数据类型 
//| y 年 m月 d日 w星期 ww周 h时 n分 s秒 
//+--------------------------------------------------- 
Date.prototype.datePart = function(interval) 
{ 
    var myDate = this; 
    var partStr=''; 
    var Week = ['日','一','二','三','四','五','六']; 
    switch (interval) 
    { 
        case 'y' :partStr = myDate.getFullYear();break; 
        case 'm' :partStr = myDate.getMonth()+1;break; 
        case 'd' :partStr = myDate.getDate();break; 
        case 'w' :partStr = Week[myDate.getDay()];break; 
        case 'ww' :partStr = myDate.WeekNumOfYear();break; 
        case 'h' :partStr = myDate.getHours();break; 
        case 'n' :partStr = myDate.getMinutes();break; 
        case 's' :partStr = myDate.getSeconds();break; 
    } 
    return partStr; 
} 
 
//+--------------------------------------------------- 
//| 取得当前日期所在月的最大天数 
//+--------------------------------------------------- 
Date.prototype.maxDayOfDate = function() 
{ 
    var myDate = this; 
    var ary = myDate.toArray(); 
    var date1 = (new Date(ary[0],ary[1]+1,1)); 
    var date2 = date1.dateAdd(1,'m',1); 
    var result = dateDiff(date1.Format('yyyy-MM-dd'),date2.Format('yyyy-MM-dd')); 
    return result; 
} 
 
//#endregion

//#region Cookie操作方法
jQuery.Cookie = function (name, value, options) {
	/// <summary>
	/// Cookie管理相关方法
	/// </summary>
	/// <param name="name"></param>
	/// <param name="value"></param>
	/// <param name="options"></param>
	/// <returns type=""></returns>
	if (typeof value != 'undefined') { // name and value given, set cookie  
		options = options || {path:""};
		if (value === null) {
			value = '';
			options.expires = -1;
		}
		value =JSON.stringify(value);
		var expires = '';
		if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString())) {
			var date;
			if (typeof options.expires == 'number') {
				date = new Date();
				date.setTime(date.getTime() + options.expires*60*1000);
			} else {
				date = options.expires;
			}
			expires = '; expires=' + date.toUTCString();
		}

		var path = options.path ? '; path=' + (options.path) : '';
		var domain = options.domain ? '; domain=' + (options.domain) : '';
		var secure = options.secure ? '; secure' : '';
		document.cookie = [name, '=', escape(value), expires, path].join('');
	}
	else {
		var cookieValue = null;
		if (document.cookie && document.cookie != '') {
			var cookies = document.cookie.split(';');
			for (var i = 0; i < cookies.length; i++) {
				var cookie = jQuery.trim(cookies[i]);
				if (cookie.substring(0, name.length + 1) == (name + '=')) {
					cookieValue = cookie.substring(name.length + 1);
					break;
				}
			}
		}
	    try{
	       return JSON.parse(unescape(cookieValue));
	    }
	    catch(ex){
	        return unescape(cookieValue);
	    }
	}
};
//#endregion

//#region 用数组模拟的双向队列
function Queue() {
    var elms = [];

    this.Append = function (obj) {
    	/// <summary>
    	/// 向队列尾部追加一个元素
    	/// </summary>
    	/// <param name="obj"></param>
        /// <returns type="Queue"></returns>
        elms.push(obj);
        return this;
    };

    this.Prepend = function (obj) {
    	/// <summary>
    	/// 向队列头部插入一个元素
    	/// </summary>
        /// <param name="obj"></param>
        /// <returns type="Queue"></returns>
        var tmp = [obj];
        elms = tmp.concat(elms);
        return this;
    };

    this.Dequeue = function () {
    	/// <summary>
    	/// 移除并返回队列头部的元素
        /// </summary>
        if (elms.length > 0) {
            return elms.shift();
        }
        else {
            return null;
        }
    };

    this.Length = function () {
        return elms.length;
    };
    return this;
}
//#endregion

//#region MD5加密函数

/**
 * jQuery MD5 hash algorithm function
 * 
 * 	<code>
 * 		Calculate the md5 hash of a String 
 * 		String $.md5 ( String str )
 * 	</code>
 * 
 * Calculates the MD5 hash of str using the 禄 RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. 
 * MD5 (Message-Digest algorithm 5) is a widely-used cryptographic hash function with a 128-bit hash value. MD5 has been employed in a wide variety of security applications, and is also commonly used to check the integrity of data. The generated hash is also non-reversable. Data cannot be retrieved from the message digest, the digest uniquely identifies the data.
 * MD5 was developed by Professor Ronald L. Rivest in 1994. Its 128 bit (16 byte) message digest makes it a faster implementation than SHA-1.
 * This script is used to process a variable length message into a fixed-length output of 128 bits using the MD5 algorithm. It is fully compatible with UTF-8 encoding. It is very useful when u want to transfer encrypted passwords over the internet. If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag). 
 * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin.
 * 
 * Example
 * 	Code
 * 		<code>
 * 			$.md5("I'm Persian."); 
 * 		</code>
 * 	Result
 * 		<code>
 * 			"b8c901d0f02223f9761016cfff9d68df"
 * 		</code>
 * 
 * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com >
 * @link http://www.semnanweb.com/jquery-plugin/md5.html
 * @see http://www.webtoolkit.info/
 * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License]
 * @param {jQuery} {md5:function(string))
 * @return string
 */

(function ($) {

	var rotateLeft = function (lValue, iShiftBits) {
		return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
	}

	var addUnsigned = function (lX, lY) {
		var lX4, lY4, lX8, lY8, lResult;
		lX8 = (lX & 0x80000000);
		lY8 = (lY & 0x80000000);
		lX4 = (lX & 0x40000000);
		lY4 = (lY & 0x40000000);
		lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
		if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
		if (lX4 | lY4) {
			if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
			else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
		} else {
			return (lResult ^ lX8 ^ lY8);
		}
	}

	var F = function (x, y, z) {
		return (x & y) | ((~x) & z);
	}

	var G = function (x, y, z) {
		return (x & z) | (y & (~z));
	}

	var H = function (x, y, z) {
		return (x ^ y ^ z);
	}

	var I = function (x, y, z) {
		return (y ^ (x | (~z)));
	}

	var FF = function (a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};

	var GG = function (a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};

	var HH = function (a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};

	var II = function (a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};

	var convertToWordArray = function (string) {
		var lWordCount;
		var lMessageLength = string.length;
		var lNumberOfWordsTempOne = lMessageLength + 8;
		var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
		var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
		var lWordArray = Array(lNumberOfWords - 1);
		var lBytePosition = 0;
		var lByteCount = 0;
		while (lByteCount < lMessageLength) {
			lWordCount = (lByteCount - (lByteCount % 4)) / 4;
			lBytePosition = (lByteCount % 4) * 8;
			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
			lByteCount++;
		}
		lWordCount = (lByteCount - (lByteCount % 4)) / 4;
		lBytePosition = (lByteCount % 4) * 8;
		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
		lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
		lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
		return lWordArray;
	};

	var wordToHex = function (lValue) {
		var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
		for (lCount = 0; lCount <= 3; lCount++) {
			lByte = (lValue >>> (lCount * 8)) & 255;
			WordToHexValueTemp = "0" + lByte.toString(16);
			WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
		}
		return WordToHexValue;
	};

	var uTF8Encode = function (string) {
		string = string.replace(/\x0d\x0a/g, "\x0a");
		var output = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				output += String.fromCharCode(c);
			} else if ((c > 127) && (c < 2048)) {
				output += String.fromCharCode((c >> 6) | 192);
				output += String.fromCharCode((c & 63) | 128);
			} else {
				output += String.fromCharCode((c >> 12) | 224);
				output += String.fromCharCode(((c >> 6) & 63) | 128);
				output += String.fromCharCode((c & 63) | 128);
			}
		}
		return output;
	};

	$.extend({
		md5: function (string) {
			var x = Array();
			var k, AA, BB, CC, DD, a, b, c, d;
			var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
			var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
			var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
			var S41 = 6, S42 = 10, S43 = 15, S44 = 21;
			string = uTF8Encode(string);
			x = convertToWordArray(string);
			a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
			for (k = 0; k < x.length; k += 16) {
				AA = a; BB = b; CC = c; DD = d;
				a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
				d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
				c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
				b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
				a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
				d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
				c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
				b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
				a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
				d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
				c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
				b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
				a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
				d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
				c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
				b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
				a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
				d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
				c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
				b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
				a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
				d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
				c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
				b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
				a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
				d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
				c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
				b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
				a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
				d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
				c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
				b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
				a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
				d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
				c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
				b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
				a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
				d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
				c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
				b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
				a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
				d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
				c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
				b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
				a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
				d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
				c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
				b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
				a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
				d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
				c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
				b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
				a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
				d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
				c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
				b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
				a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
				d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
				c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
				b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
				a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
				d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
				c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
				b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
				a = addUnsigned(a, AA);
				b = addUnsigned(b, BB);
				c = addUnsigned(c, CC);
				d = addUnsigned(d, DD);
			}
			var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
			return tempValue.toLowerCase();
		}
	});
})(jQuery);

//#endregion

function getUrlParam(name) {
    /// <summary>
    /// 从当前页面路径中获取指定名称的参数项
    /// </summary>
    /// <param name="name"></param>
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象

    var r = window.location.search.substr(1).match(reg);  //匹配目标参数
    if (r != null) {
        return decodeURI(unescape(r[2]));
    }
    else {
        return null
    }; //返回参数值
}

function setUrlParam(url, name, value) {
    var newUrl="";
    var splitIndex = url.indexOf("?") + 1;
    var paramStr = url.substr(splitIndex, url.length);

        newUrl= url.substr(0, splitIndex);

    // - if exist , replace 
    var arr = paramStr.split('&');
    for (var i = 0; i < arr.length; i++) {
        var kv = arr[i].split('=');
        if (kv[0] == name) {
            newUrl += kv[0] + "=" + value;
        } else {
            if (kv[1] != undefined) {
                newUrl += kv[0] + "=" + kv[1];
            }
        }
        if (i != arr.length - 1) {
            newUrl += "&";
        }
    }

    // - if new, add
    if (newUrl.indexOf(name) < 0) {
        newUrl += splitIndex == 0 ? "?" + name + "=" + value : "&" + name + "=" + value;
    }
    url = newUrl;
    return newUrl;
}

function GetCurrency(currency, money) {
    /// <summary>
    /// 将一个money值转换为对应货币形式
    /// </summary>
    /// <param name="currency">货币单位，默认“CNY”,USD,CNY</param>
    /// <param name="money">表示金额的数值</param>
    if (!currency) {
        return '￥：' + money;
    }
    switch (currency) {
        case "USD":
            return "$：" + money;
        case "CNY":
        default:
            return '￥：' + money;
    }
}

//#region 用于页面初始化的JS对象
if (!window.SoBiz) {
    $.ajax({
        cache: false,
        async: true,
        timeout: 30000,
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        complete: function (rtn, ev) {
            if (rtn.status == '401') {
                error("会话过期", "这通常是由于太长时间没有操作引起，请您重新登录", 5).on("disposed", function () { window.location = "/Index.html"; });
            }
            else if (rtn.status == '500') {
                //TODO:通用Debug方法发回给服务器
                SoBiz.Debug(JSON.stringify(rtn),"ServerCrash");
                error("抱歉","服务器正忙，这通常是由于预料之外的情况，我们已记录并通知管理人员，请您稍后再试")
            }
            else {
                
            }
        }
    });

    SoBiz = {
        IsReady: false,
        _isReady: [],
        _processbar: null,
        Template: function (tplname) {
            /// <summary>
            /// 以指定的模板重新加载当前页面
            /// </summary>
            /// <param name="tplname" type="type">模板名称</param>
            /// <returns type=""></returns>
            /// <summary>
            /// 初始化页面模板
            /// </summary>
            /// <param name="tplname" type="type">用指定页面模板初始化当前页面</param>
            if (SoBiz.IsReady) {
                return window.SoBiz;
            }
            SoBiz._processbar = $("<div class='pageLoading' style='position: fixed;bottom:0;right:100%;height: 6px;width: 100%;background-color: #008ed3;z-index:100000;background-repeat:no-repeat;background-position:center center;background-size:120px'>")
                                    .appendTo("html");
            SoBiz._processbar.css("right", "70%");
            //等待当前页面内容下载完毕，临时保存当前页面的内容
            $(document).ready(function () {
                var body = $("body").hide();
                var tmp = body[0].innerHTML;
                body[0].innerHTML = "";


                var host = $("<div>").appendTo(body).hide();
                //加载模板页面
                body.load("/common/" + tplname + ".html", function () {
                    $(this).children("meta").prependTo(document.head);
                    $(this).children("link").prependTo(document.head);

                    //将原页面内容创建一个临时元素放在body中   
                    var cntId = "tmp-wraper" + Math.random();
                    var cnt = $("<div>").appendTo(body).hide().attr("id", cntId);
                    cnt[0].innerHTML = tmp;

                    //找到模板中定义的所有section
                    var secsTpl = body.find("[section]");

                    //从原页面内容中查找具有相同section属性的内容，替换到模板中
                    secsTpl.each(function (s) {
                        var sec = $(this).attr("section");
                        if (sec) {
                            var tgt = cnt.find("[section=" + sec + "]");
                            if (tgt.length > 0) {
                                var src = tgt.attr("src");
                                if (src) {
                                    $(this).attr("data-src", src);
                                }
                                else {
                                    this.innerHTML = tgt[0].innerHTML;
                                }
                                tgt.remove();
                            }
                        }
                    });

                    SoBiz._processbar.css("right", "20%");

                    cnt.children().appendTo(body);  //如果直接用innerHTML，有些脚本不会被执行

                    SoBiz.IsReady = true;
                    SoBiz._isReady.forEach(function (c) {
                        try {
                            c.call(this);
                        }
                        catch (ex) {
                            SoBiz.Debug(ex.stack, "UIException");
                        }
                    });
                    SoBiz._isReady = [];

                    //移除临时内容
                    $(cntId).remove();

                    //加载data-src指定的内容
                    body.find("[data-src]").each(function (s) {
                        $(this).load($(this).attr("data-src"));
                    });
                    body.fadeIn();
                    SoBiz._processbar.css("right", "0");
                    setTimeout(function () { SoBiz._processbar.remove(); }, 1000);
                });
            });

            //TODO:页面加载完毕
            return window.SoBiz;
        },
        Ready: function (fnOnSuccess) {
            if (SoBiz.IsReady) {
                if (ObjHelper.IsFunc(fnOnSuccess)) {
                    try {
                        fnOnSuccess.call(this);
                    }
                    catch (ex) {
                        SoBiz.Debug(ex.stack, "UIException");
                    }
                }
            }
            else {
                SoBiz._isReady.push(fnOnSuccess);
            }
        },
        Login: function (fnOnSuccess, fnOnFailure) {
            /// <summary>
            /// 检查登录状态
            /// </summary>
            /// <param name="fnOnSuccess" type="type">登录成功后的回调</param>
            /// <param name="fnOnFailure" type="type">登录失败后的回调</param>
            if (!window.User) {
                $.getJSON("/MyBiz/GetUserInfo", {}, function (rtn) {
                    if (rtn.IsPositive) {
                        if (!window.User) {
                            //避免重复加载
                            window.User = rtn.Data;
                            if (window.fullSetting) {
                                User.setting = mesh(fullSetting, JSON.parse(User.setting), "Title");
                            }
                        }
                        if (ObjHelper.IsFunc(fnOnSuccess)) {
                            try {
                                fnOnSuccess.call(this);
                            }
                            catch (ex) {
                                SoBiz.Debug(ex.stack, "UIException");
                            }
                        }

                    }
                    else {
                        if (ObjHelper.IsFunc(fnOnFailure)) {
                            fnOnFailure.call(this);
                        }
                        else {
                            //回到登录页，并记录登录后应返回的地址
                            $.Cookie("backto", window.location.href, { path: "/" });
                            window.location = "/Index2.html?tm=" + new Date().getTime().toString();
                        }
                    }
                });
            }
            else {
                if (ObjHelper.IsFunc(fnOnSuccess)) {
                    try {
                        fnOnSuccess.call(this);
                    }
                    catch (ex) {
                        SoBiz.Debug(ex.stack, "UIException");
                    }
                }
            }
        },
        LoginWX: function (fnOnSuccess) {
            /// <summary>
            /// 登录并获取微信登录状态和微信信息[注意：并不代表登录平台成功]
            /// </summary>
            /// <param name="fnOnSuccess" type="type"></param>
            if (!window.WxUser) {
                $.getJSON("/TLB2B/GetUserInfo", null, function (rtn) {
                    if (rtn.IsPositive) {
                        if (!window.WxUser) {
                            window.WxUser = JSON.parse(rtn.Data);
                            if (!WxUser.nickname) {
                                WxUser = JSON.parse(WxUser);
                            }
                        }
                        //$.post("/SoBiz/Login", { opensrc: "wechat" }); //尝试使用微信执行开放登录
                        if (ObjHelper.IsFunc(fnOnSuccess)) {
                            try {
                                fnOnSuccess.call(this);
                            }
                            catch (ex) {
                                SoBiz.Debug(ex.stack, "UIException");
                            }
                        }
                    }
                    else {
                        window.location = "/TLB2B/WxOauthBegin?fromurl=" + encodeURI(window.location);
                    }
                });
            }
            else {
                if (ObjHelper.IsFunc(fnOnSuccess)) {
                    try {
                        fnOnSuccess.call(this);
                    }
                    catch (ex) {
                        SoBiz.Debug(ex.stack, "UIException");
                    }
                }
            }
        },
        on: function (event, fnCallback) {
            /// <summary>
            /// 绑定全局状态事件[DataRangeChanged]
            /// </summary>
            /// <param name="event" type="type"></param>
            /// <param name="fnCallback" type="type"></param>
            $("body").on(event, fnCallback);
        },
        off: function (event, fnCallback) {
            /// <summary>
            /// 解除全局状态事件绑定
            /// </summary>
            /// <param name="event" type="type">要解除的事件类型</param>
            /// <param name="fnCallback" type="type">要解除的回调方法</param>
            $("body").off(event, fnCallback);
        },
        trigger: function (event, data) {
            /// <summary>
            /// 发出全局事件通知
            /// </summary>
            /// <param name="event" type="type">事件类型</param>
            /// <param name="data" type="type">事件参数</param>
            try {
                $("body").trigger(event, data);
            }
            catch (ex) {
                SoBiz.Debug(ex.stack, "UIException");
            }

        },
        CheckAuthor: function (obj, elm) {
            /// <summary>
            /// 根据指定数据对象检查相关元素的权限
            /// </summary>
            /// <param name="obj" type="type">元素相关的数据对象</param>
            /// <param name="elm" type="type">需要权限控制的页面元素【含子级元素】</param>
            if (!elm) {
                elm = $("#pageContent");
            }
            //检查所有需要检查obj-auth的元素
            elm.find("[obj-auth]").each(function () {
                var e = $(this);
                var flag = false;
                var h = e.attr("execute");

                //首先，根据obj-role检查此元素是否
                var roles = e.attr("obj-role");
                if (roles) {
                    roles = roles.split('|');
                    roles.forEach(function (r) {
                        if (obj[r] && obj[r].idstr === User.idstr) {
                            flag = true;
                        }
                    })
                }

                //如果检查没通过，或者没有指定obj-role
                //如果指定了obj-org和obj-action，则再检查数据权限
                if (!flag) {
                    var orgs = e.attr("obj-org");  //元素上通过此属性指示如何获取数据对象的所属组织架构
                    var act = e.attr("obj-action");  //DOM元素上通过此属性指示所需的动作权限
                    if (orgs) {
                        orgs = orgs.split('|');
                        orgs.forEach(function (c) {
                            if (!flag) {
                                var objOrg = obj[c];
                                if (objOrg) {
                                    //首先判断用户是否拥有此数据所属组织架构的权限
                                    var aorg = User.AuthedOrgs.findObj("idstr", objOrg);
                                    //如果指定了需要动作权限，则再判断用户在是否拥有动作权限
                                    //TODO：判断用户获得动作权限的岗位所属部门是否高于订单所属部门
                                    if (act && aorg) {
                                        if (User.Authority.findObj("auth", act) != null) {
                                            flag = true;
                                        }
                                    }
                                    else if (aorg) {
                                        flag = true;
                                    }
                                    else {

                                    }
                                }
                            }
                        })
                    }
                }


                //根据检查结果和指定的处理方式
                if (!flag) {
                    if (!h) {
                        e.remove();
                    }
                    else if (h == 'disable') {
                        e.disable();
                    }
                    else if (h == 'deny') {
                        error("缺少权限", "您无权查看此数据", 5, function () { window.history.go(-1); });
                    }
                    else {
                        e.vl("-");
                    }
                }
            });

            //检查所有需要特定obj-status的元素，检查结果默认是采取禁用的方式处理
            elm.find("[obj-status]").each(function () {
                var e = $(this);
                var ss = e.attr("obj-status").split('|');
                var sflag = false;
                ss.forEach(function (s) {
                    if (obj.status == s) {
                        sflag = true;
                    }
                })
                if (!sflag) {
                    if (e.attr("execute") == 'disable') {
                        e.disable();
                    }
                    else {
                        e.remove();
                    }
                }
            })
        },
        Debug: function (msg, errType) {
            /// <summary>
            /// 记录页面上的错误信息，并尝试回传给服务器用于错误分析
            /// </summary>
            /// <param name="msg" type="type"></param>
            var err = {
                url: window.location.href,
                message: msg,
                error: errType || "unknow",
                acnt: window.User ? User.idstr : "no user",
                wxAcnt: window.WxUser ? WxUser.nickname : "no wxuser"
            }
            $.getJSON("/CloudAdmin/Debug", err);
        }
    };

    $(function () {
        SoBiz.IsReady = true;
    });
};
User: null;
WxUser: null;
//#endregion